package scau.mis4.chanyulin.base.common;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import scau.mis4.chanyulin.dictionary.Code;
import scau.mis4.chanyulin.entity.Employee;
import scau.mis4.chanyulin.service.IEmployeeService;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Validator;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by cyl on 2016/11/26.
 */
@CrossOrigin(origins = {"http://localhost:3000","http://apizza.cc"}, allowCredentials = "true")
public abstract class BaseController {
    protected Logger logger=LogManager.getLogger(getClass());

    @Autowired
    private IEmployeeService employeeService;

    /**
     * 验证Bean实例对象
     */
    @Autowired
    protected Validator validator;

    /**
     * 获取当前已登录用户的账号
     * @return
     */
    protected String getLoginedUserId() {
        Subject subject = SecurityUtils.getSubject();
        String username = (String) subject.getPrincipal();
        List<Employee> employeeList = employeeService.findSelectPropertyWhereAnd("name", username,"id");
        if(employeeList.size() != 0) {
            return employeeList.get(0).getId();
        }
        return "未登录或者无此账号";
    }


    protected String doLogin(String username, String password) {
        SecurityUtils.getSecurityManager().logout(SecurityUtils.getSubject());
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        org.apache.shiro.subject.Subject subject = SecurityUtils.getSubject();
        token.setRememberMe(true);
        try {
            subject.login(token);
        } catch (UnknownAccountException ex) {
            logger.catching(ex);
            return "账号不存在";
        } catch (IncorrectCredentialsException ex) {
            logger.catching(ex);
            return "账号或密码错误";
        }
        return "登录成功";
    }


    /**
     * 添加Model消息
     * @param messages
     */
    protected void addMessage(Model model, String... messages) {
        StringBuilder sb = new StringBuilder();
        for (String message : messages){
            sb.append(message).append(messages.length>1?"<br/>":"");
        }
        model.addAttribute("message", sb.toString());


    }

    protected void sendCode(Model model,Code code){
        model.addAttribute("statusCode",code.getCode());
        model.addAttribute("statusMsg",code.getMessage());
    }
    protected void sendCode(Map map, Code code){
        map.put("statusCode",code.getCode());
        map.put("statusMsg",code.getMessage());
    }

    protected String createJSONByBool(boolean bool) {
        if (bool)
            return createSuccessJSON();
        else
            return createErrorJSON();
    }

    protected String createJSONByBool(boolean bool, Model model) {
        if (bool)
            return createSuccessJSON(model);
        else
            return createErrorJSON(model);
    }

    protected String createJSONByBool(boolean bool, Map map) {
        if (bool)
            return createSuccessJSON(map);
        else
            return createErrorJSON(map);
    }

    protected String createJSONByNull(Object obj) {
        if (obj == null)
            return createErrorJSON();
        else
            return createSuccessJSON();
    }

    protected String createJSONByNull(Object obj, Model model) {
        if (obj == null)
            return createErrorJSON(model);
        else
            return createSuccessJSON(model);
    }

    protected String createJSONByNull(Object obj, Map map) {
        if (obj == null)
            return createErrorJSON(map);
        else
            return createSuccessJSON(map);
    }

    protected String createJSONByUpdates(int updates) {
        if (updates <= 0)
            return createErrorJSON();
        else
            return createSuccessJSON();
    }

    protected String createJSONByUpdates(int updates, Model model) {
        if (updates <= 0)
            return createErrorJSON(model);
        else
            return createSuccessJSON(model);
    }

    protected String createJSONByUpdates(int updates, Map map) {
        if (updates <= 0)
            return createErrorJSON(map);
        else
            return createSuccessJSON(map);
    }

    protected String createSuccessJSON(String successInfo) {
        Map map = new HashMap();
        map.put("statusCode", "0");
        map.put("statusMsg", successInfo);
        return JSON.toJSONString(map);
    }

    protected String createSuccessJSON() {
        Code code = Code.OPERATION_SUCCESS;
        Model model = new ExtendedModelMap();
        model.addAttribute("statusCode", code.getCode());
        model.addAttribute("statusMsg", code.getMessage());
        return JSON.toJSONString(model);
    }

    protected String createSuccessJSON(Model model) {
        Code code = Code.OPERATION_SUCCESS;
        model.addAttribute("statusCode", code.getCode());
        model.addAttribute("statusMsg", code.getMessage());
        return JSON.toJSONString(model);
    }

    protected String createSuccessJSON(Map map) {
        Code code = Code.OPERATION_SUCCESS;
        map.put("statusCode", code.getCode());
        map.put("statusMsg", code.getMessage());
        return JSON.toJSONString(map);
    }

    protected String createErrorJSON() {
        Code code = Code.OPERATION_ERROR;
        Model model = new ExtendedModelMap();
        model.addAttribute("statusCode", code.getCode());
        model.addAttribute("statusMsg", code.getMessage());
        return JSON.toJSONString(model);
    }

    protected String createErrorJSON(Model model) {
        Code code = Code.OPERATION_ERROR;
        model.addAttribute("statusCode", code.getCode());
        model.addAttribute("statusMsg", code.getMessage());
        return JSON.toJSONString(model);
    }

    protected String createErrorJSON(Map map) {
        Code code = Code.OPERATION_ERROR;
        map.put("statusCode", code.getCode());
        map.put("statusMsg", code.getMessage());
        return JSON.toJSONString(map);
    }

    protected String createErrorJSON(String errorInfo) {
        Map map = new HashMap();
        map.put("statusCode", "1");
        map.put("statusMsg", errorInfo);
        return JSON.toJSONString(map);
    }

    protected String createErrorJSON(String errorInfo, String statusCode){
        Map map = new HashMap();
        map.put("statusCode", statusCode);
        map.put("statusMsg", errorInfo);
        return JSON.toJSONString(map);
    }


    /**重定向转发消息
     * 添加Flash消息
     * return "redirect:/.."
     * @param messages
     */
    protected void addMessage(RedirectAttributes redirectAttributes, String... messages) {
        StringBuilder sb = new StringBuilder();
        for (String message : messages){
            sb.append(message).append(messages.length>1?"<br/>":"");
        }
        redirectAttributes.addFlashAttribute("message", sb.toString());
    }

    /**
     * 客户端返回字符串
     * @param response
     * @param string
     * @return
     */
    protected String renderString(HttpServletResponse response, String string, String type) {
        try {
            response.reset();
            response.setContentType(type);
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);
            return null;
        } catch (IOException e) {
            return null;
        }
    }
    @ExceptionHandler(value = {UnauthorizedException.class})
    @ResponseBody
    public Map catchUnauthorizedException(UnauthorizedException ex) {
        Map map = new LinkedHashMap<>();
        map.put("statusCode",Code.REJECT.getCode());
        map.put("statusMsg",Code.REJECT.getMessage());
        logger.catching(ex);
        return map;
    }
    @ExceptionHandler(value = {RuntimeException.class})
    @ResponseBody
    public Map catchRuntimeException(RuntimeException ex) {
        Map map = new LinkedHashMap<>();
        map.put("statusCode",Code.REJECT.getCode());
        map.put("statusMsg","系统异常");
        logger.catching(ex);
        return map;
    }

    /**
     * 授权登录异常
      */
//    @ExceptionHandler({AuthenticationException.class})
//    @ResponseBody
//    public String authenticationException() {
//        return "error/403";
//    }
//    @ExceptionHandler({UnauthenticatedException.class})
//    @ResponseBody
//    public Map authenticationException() {
//        Map map = new LinkedHashMap<>();
//        map.put("statusCode", Code.REJECT.getCode());
//        map.put("statusMsg", Code.REJECT.getMessage());
//        return map;
//    }

    /**
     * 初始化数据绑定
     * 1. 将所有传递进来的String进行HTML编码，防止XSS攻击
     * 2. 将字段中Date类型转换为String类型
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        // String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
            }
            @Override
            public String getAsText() {
                Object value = getValue();
                return value != null ? value.toString() : "";
            }
        });
        // Date 类型转换
//        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
//            @Override
//            public void setAsText(String text) {
//                setValue(DateUtils.parseDate(text));
//            }
//			@Override
//			public String getAsText() {
//				Object value = getValue();
//				return value != null ? DateUtils.formatDateTime((Date)value) : "";
//			}
//        });
    }
}
